/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is ART Ontology API.
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2007.
 * All Rights Reserved.
 *
 * ART Ontology API was developed by the Artificial Intelligence Research Group
 * (art.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about the ART Ontology API can be obtained at 
 * http//art.uniroma2.it/owlart
 *
 */

/*
 * Contributor(s): Armando Stellato stellato@info.uniroma2.it
 */
package it.uniroma2.art.owlart.vocabulary;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;

import it.uniroma2.art.owlart.exceptions.VocabularyInitializationException;
import it.uniroma2.art.owlart.model.ARTNodeFactory;
import it.uniroma2.art.owlart.model.ARTURIResource;

/*
 * TODO we could create a subclass of ARTURIResource for datatypes, which contains itself the method for
 * recognizing if a given value is valid for that datatype
 * */

/**
 * Vocabulary file for the XML language specification
 * 
 * @author Armando Stellato
 * 
 */
public class XmlSchema {

	/*
	 * The XML Schema namespace
	 */

	/** The XML Schema namespace (<tt>http://www.w3.org/2001/XMLSchema#</tt>). **/
	public static final String NAMESPACE = "http://www.w3.org/2001/XMLSchema#";

	/*
	 * Primitive datatypes
	 */

	/** <tt>http://www.w3.org/2001/XMLSchema#duration</tt> **/
	public static final String DURATION = NAMESPACE + "duration";

	/** <tt>http://www.w3.org/2001/XMLSchema#dateTime</tt> **/
	public static final String DATETIME = NAMESPACE + "dateTime";

	/** <tt>http://www.w3.org/2001/XMLSchema#time</tt> **/
	public static final String TIME = NAMESPACE + "time";

	/** <tt>http://www.w3.org/2001/XMLSchema#date</tt> **/
	public static final String DATE = NAMESPACE + "date";

	/** <tt>http://www.w3.org/2001/XMLSchema#gYearMonth</tt> **/
	public static final String GYEARMONTH = NAMESPACE + "gYearMonth";

	/** <tt>http://www.w3.org/2001/XMLSchema#gYear</tt> **/
	public static final String GYEAR = NAMESPACE + "gYear";

	/** <tt>http://www.w3.org/2001/XMLSchema#gMonthDay</tt> **/
	public static final String GMONTHDAY = NAMESPACE + "gMonthDay";

	/** <tt>http://www.w3.org/2001/XMLSchema#gDay</tt> **/
	public static final String GDAY = NAMESPACE + "gDay";

	/** <tt>http://www.w3.org/2001/XMLSchema#gMonth</tt> **/
	public static final String GMONTH = NAMESPACE + "gMonth";

	/** <tt>http://www.w3.org/2001/XMLSchema#string</tt> **/
	public static final String STRING = NAMESPACE + "string";

	/** <tt>http://www.w3.org/2001/XMLSchema#boolean</tt> **/
	public static final String BOOLEAN = NAMESPACE + "boolean";

	/** <tt>http://www.w3.org/2001/XMLSchema#base64Binary</tt> **/
	public static final String BASE64BINARY = NAMESPACE + "base64Binary";

	/** <tt>http://www.w3.org/2001/XMLSchema#hexBinary</tt> **/
	public static final String HEXBINARY = NAMESPACE + "hexBinary";

	/** <tt>http://www.w3.org/2001/XMLSchema#float</tt> **/
	public static final String FLOAT = NAMESPACE + "float";

	/** <tt>http://www.w3.org/2001/XMLSchema#decimal</tt> **/
	public static final String DECIMAL = NAMESPACE + "decimal";

	/** <tt>http://www.w3.org/2001/XMLSchema#double</tt> **/
	public static final String DOUBLE = NAMESPACE + "double";

	/** <tt>http://www.w3.org/2001/XMLSchema#anyURI</tt> **/
	public static final String ANYURI = NAMESPACE + "anyURI";

	/** <tt>http://www.w3.org/2001/XMLSchema#QName</tt> **/
	public static final String QNAME = NAMESPACE + "QName";

	/** <tt>http://www.w3.org/2001/XMLSchema#NOTATION</tt> **/
	public static final String NOTATION = NAMESPACE + "NOTATION";

	/*
	 * Derived datatypes
	 */

	/** <tt>http://www.w3.org/2001/XMLSchema#normalizedString</tt> **/
	public static final String NORMALIZEDSTRING = NAMESPACE + "normalizedString";

	/** <tt>http://www.w3.org/2001/XMLSchema#token</tt> **/
	public static final String TOKEN = NAMESPACE + "token";

	/** <tt>http://www.w3.org/2001/XMLSchema#language</tt> **/
	public static final String LANGUAGE = NAMESPACE + "language";

	/** <tt>http://www.w3.org/2001/XMLSchema#NMTOKEN</tt> **/
	public static final String NMTOKEN = NAMESPACE + "NMTOKEN";

	/** <tt>http://www.w3.org/2001/XMLSchema#NMTOKENS</tt> **/
	public static final String NMTOKENS = NAMESPACE + "NMTOKENS";

	/** <tt>http://www.w3.org/2001/XMLSchema#Name</tt> **/
	public static final String NAME = NAMESPACE + "Name";

	/** <tt>http://www.w3.org/2001/XMLSchema#NCName</tt> **/
	public static final String NCNAME = NAMESPACE + "NCName";

	/** <tt>http://www.w3.org/2001/XMLSchema#ID</tt> **/
	public static final String ID = NAMESPACE + "ID";

	/** <tt>http://www.w3.org/2001/XMLSchema#IDREF</tt> **/
	public static final String IDREF = NAMESPACE + "IDREF";

	/** <tt>http://www.w3.org/2001/XMLSchema#IDREFS</tt> **/
	public static final String IDREFS = NAMESPACE + "IDREFS";

	/** <tt>http://www.w3.org/2001/XMLSchema#ENTITY</tt> **/
	public static final String ENTITY = NAMESPACE + "ENTITY";

	/** <tt>http://www.w3.org/2001/XMLSchema#ENTITIES</tt> **/
	public static final String ENTITIES = NAMESPACE + "ENTITIES";

	/** <tt>http://www.w3.org/2001/XMLSchema#integer</tt> **/
	public static final String INTEGER = NAMESPACE + "integer";

	/** <tt>http://www.w3.org/2001/XMLSchema#long</tt> **/
	public static final String LONG = NAMESPACE + "long";

	/** <tt>http://www.w3.org/2001/XMLSchema#int</tt> **/
	public static final String INT = NAMESPACE + "int";

	/** <tt>http://www.w3.org/2001/XMLSchema#short</tt> **/
	public static final String SHORT = NAMESPACE + "short";

	/** <tt>http://www.w3.org/2001/XMLSchema#byte</tt> **/
	public static final String BYTE = NAMESPACE + "byte";

	/** <tt>http://www.w3.org/2001/XMLSchema#nonPositiveInteger</tt> **/
	public static final String NON_POSITIVE_INTEGER = NAMESPACE + "nonPositiveInteger";

	/** <tt>http://www.w3.org/2001/XMLSchema#negativeInteger</tt> **/
	public static final String NEGATIVE_INTEGER = NAMESPACE + "negativeInteger";

	/** <tt>http://www.w3.org/2001/XMLSchema#nonNegativeInteger</tt> **/
	public static final String NON_NEGATIVE_INTEGER = NAMESPACE + "nonNegativeInteger";

	/** <tt>http://www.w3.org/2001/XMLSchema#positiveInteger</tt> **/
	public static final String POSITIVE_INTEGER = NAMESPACE + "positiveInteger";

	/** <tt>http://www.w3.org/2001/XMLSchema#unsignedLong</tt> **/
	public static final String UNSIGNED_LONG = NAMESPACE + "unsignedLong";

	/** <tt>http://www.w3.org/2001/XMLSchema#unsignedInt</tt> **/
	public static final String UNSIGNED_INT = NAMESPACE + "unsignedInt";

	/** <tt>http://www.w3.org/2001/XMLSchema#unsignedShort</tt> **/
	public static final String UNSIGNED_SHORT = NAMESPACE + "unsignedShort";

	/** <tt>http://www.w3.org/2001/XMLSchema#unsignedByte</tt> **/
	public static final String UNSIGNED_BYTE = NAMESPACE + "unsignedByte";

	// UTILITY METHODS

	/**
	 * as for {@link #formatDateTime(int, int, int, int, int, int, String)} with last argument equal to "Z"
	 * 
	 * @param year
	 * @param month
	 * @param day
	 * @param hour
	 * @param minute
	 * @param second
	 * @return
	 * @throws InconsistentDataException
	 */
	public static String formatDateTime(int year, int month, int day, int hour, int minute, int second) {
		return formatDateTime(year, month, day, hour, minute, second, "Z");
	}

	/**
	 * formats a dateTime value following ISO-8601 standard
	 * 
	 * @param year
	 * @param month
	 * @param day
	 * @param hour
	 * @param minute
	 * @param second
	 * @param offset
	 * @return
	 * @throws InconsistentDataException
	 */
	public static String formatDateTime(int year, int month, int day, int hour, int minute, int second,
			String offset) {
		return year + ":" + month + ":" + day + "T" + hour + ":" + minute + ":" + second + offset;
	}

	private static SimpleDateFormat iso8601DateTimeLocalFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
	private static SimpleDateFormat iso8601DateTimeUTCFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");

	public static String formatDateTime(Date date) {
		return iso8601DateTimeUTCFormat.format(date);
	}

	public static String formatCurrentLocalDateTime() {
		return iso8601DateTimeLocalFormat.format(new Date());
	}

	public static String formatCurrentUTCDateTime() {
		return iso8601DateTimeUTCFormat.format(new Date());
	}
	
	static {
		iso8601DateTimeUTCFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
	}
	
	
	public static class Res {

		public static HashSet<ARTURIResource> primitiveDatatypes = new HashSet<ARTURIResource>();
		public static HashSet<ARTURIResource> derivedDatatypes = new HashSet<ARTURIResource>();
		public static HashSet<ARTURIResource> allDatatypes = new HashSet<ARTURIResource>();

		/*
		 * Primitive datatypes
		 */

		public static ARTURIResource DURATION;

		public static ARTURIResource DATETIME;

		public static ARTURIResource TIME;

		public static ARTURIResource DATE;

		public static ARTURIResource GYEARMONTH;

		public static ARTURIResource GYEAR;

		public static ARTURIResource GMONTHDAY;

		public static ARTURIResource GDAY;

		public static ARTURIResource GMONTH;

		public static ARTURIResource STRING;

		public static ARTURIResource BOOLEAN;

		public static ARTURIResource BASE64BINARY;

		public static ARTURIResource HEXBINARY;

		public static ARTURIResource FLOAT;

		public static ARTURIResource DECIMAL;

		public static ARTURIResource DOUBLE;

		public static ARTURIResource ANYURI;

		public static ARTURIResource QNAME;

		public static ARTURIResource NOTATION;

		/*
		 * Derived datatypes
		 */

		public static ARTURIResource NORMALIZEDSTRING;

		public static ARTURIResource TOKEN;

		public static ARTURIResource LANGUAGE;

		public static ARTURIResource NMTOKEN;

		public static ARTURIResource NMTOKENS;

		public static ARTURIResource NAME;

		public static ARTURIResource NCNAME;

		public static ARTURIResource ID;

		public static ARTURIResource IDREF;

		public static ARTURIResource IDREFS;

		public static ARTURIResource ENTITY;

		public static ARTURIResource ENTITIES;

		public static ARTURIResource INTEGER;

		public static ARTURIResource LONG;

		public static ARTURIResource INT;

		public static ARTURIResource SHORT;

		public static ARTURIResource BYTE;

		public static ARTURIResource NON_POSITIVE_INTEGER;

		public static ARTURIResource NEGATIVE_INTEGER;

		public static ARTURIResource NON_NEGATIVE_INTEGER;

		public static ARTURIResource POSITIVE_INTEGER;

		public static ARTURIResource UNSIGNED_LONG;

		public static ARTURIResource UNSIGNED_INT;

		public static ARTURIResource UNSIGNED_SHORT;

		public static ARTURIResource UNSIGNED_BYTE;

		static {
			try {
				initialize(VocabUtilities.nodeFactory);
			} catch (VocabularyInitializationException e) {
				e.printStackTrace(System.err);
			}
		}

		public static void initialize(ARTNodeFactory nodeFact) throws VocabularyInitializationException {

			/*
			 * Primitive datatypes
			 */
			DURATION = nodeFact.createURIResource(XmlSchema.DURATION);
			DATETIME = nodeFact.createURIResource(XmlSchema.DATETIME);
			TIME = nodeFact.createURIResource(XmlSchema.TIME);
			DATE = nodeFact.createURIResource(XmlSchema.DATE);
			GYEARMONTH = nodeFact.createURIResource(XmlSchema.GYEARMONTH);
			GYEAR = nodeFact.createURIResource(XmlSchema.GYEAR);
			GMONTHDAY = nodeFact.createURIResource(XmlSchema.GMONTHDAY);
			GDAY = nodeFact.createURIResource(XmlSchema.GDAY);
			GMONTH = nodeFact.createURIResource(XmlSchema.GMONTH);
			STRING = nodeFact.createURIResource(XmlSchema.STRING);
			BOOLEAN = nodeFact.createURIResource(XmlSchema.BOOLEAN);
			BASE64BINARY = nodeFact.createURIResource(XmlSchema.BASE64BINARY);
			HEXBINARY = nodeFact.createURIResource(XmlSchema.HEXBINARY);
			FLOAT = nodeFact.createURIResource(XmlSchema.FLOAT);
			DECIMAL = nodeFact.createURIResource(XmlSchema.DECIMAL);
			DOUBLE = nodeFact.createURIResource(XmlSchema.DOUBLE);
			ANYURI = nodeFact.createURIResource(XmlSchema.ANYURI);
			QNAME = nodeFact.createURIResource(XmlSchema.QNAME);
			NOTATION = nodeFact.createURIResource(XmlSchema.NOTATION);
			/*
			 * Derived datatypes
			 */

			NORMALIZEDSTRING = nodeFact.createURIResource(XmlSchema.NORMALIZEDSTRING);
			TOKEN = nodeFact.createURIResource(XmlSchema.TOKEN);
			LANGUAGE = nodeFact.createURIResource(XmlSchema.LANGUAGE);
			NMTOKEN = nodeFact.createURIResource(XmlSchema.NMTOKEN);
			NMTOKENS = nodeFact.createURIResource(XmlSchema.NMTOKENS);
			NAME = nodeFact.createURIResource(XmlSchema.NAME);
			NCNAME = nodeFact.createURIResource(XmlSchema.NCNAME);
			ID = nodeFact.createURIResource(XmlSchema.ID);
			IDREF = nodeFact.createURIResource(XmlSchema.IDREF);
			IDREFS = nodeFact.createURIResource(XmlSchema.IDREFS);
			ENTITY = nodeFact.createURIResource(XmlSchema.ENTITY);
			ENTITIES = nodeFact.createURIResource(XmlSchema.ENTITIES);
			INTEGER = nodeFact.createURIResource(XmlSchema.INTEGER);
			LONG = nodeFact.createURIResource(XmlSchema.LONG);
			INT = nodeFact.createURIResource(XmlSchema.INT);
			SHORT = nodeFact.createURIResource(XmlSchema.SHORT);
			BYTE = nodeFact.createURIResource(XmlSchema.BYTE);
			NON_POSITIVE_INTEGER = nodeFact.createURIResource(XmlSchema.NON_POSITIVE_INTEGER);
			NEGATIVE_INTEGER = nodeFact.createURIResource(XmlSchema.NEGATIVE_INTEGER);
			NON_NEGATIVE_INTEGER = nodeFact.createURIResource(XmlSchema.NON_NEGATIVE_INTEGER);
			POSITIVE_INTEGER = nodeFact.createURIResource(XmlSchema.POSITIVE_INTEGER);
			UNSIGNED_LONG = nodeFact.createURIResource(XmlSchema.UNSIGNED_LONG);
			UNSIGNED_INT = nodeFact.createURIResource(XmlSchema.UNSIGNED_INT);
			UNSIGNED_SHORT = nodeFact.createURIResource(XmlSchema.UNSIGNED_SHORT);
			UNSIGNED_BYTE = nodeFact.createURIResource(XmlSchema.UNSIGNED_BYTE);

			primitiveDatatypes.add(DURATION);
			primitiveDatatypes.add(DATETIME);
			primitiveDatatypes.add(TIME);
			primitiveDatatypes.add(DATE);
			primitiveDatatypes.add(GYEARMONTH);
			primitiveDatatypes.add(GYEAR);
			primitiveDatatypes.add(GMONTHDAY);
			primitiveDatatypes.add(GDAY);
			primitiveDatatypes.add(GMONTH);
			primitiveDatatypes.add(STRING);
			primitiveDatatypes.add(BOOLEAN);
			primitiveDatatypes.add(BASE64BINARY);
			primitiveDatatypes.add(HEXBINARY);
			primitiveDatatypes.add(FLOAT);
			primitiveDatatypes.add(DECIMAL);
			primitiveDatatypes.add(DOUBLE);
			primitiveDatatypes.add(ANYURI);
			primitiveDatatypes.add(QNAME);
			primitiveDatatypes.add(NOTATION);

			derivedDatatypes.add(NORMALIZEDSTRING);
			derivedDatatypes.add(TOKEN);
			derivedDatatypes.add(LANGUAGE);
			derivedDatatypes.add(NMTOKEN);
			derivedDatatypes.add(NMTOKENS);
			derivedDatatypes.add(NAME);
			derivedDatatypes.add(NCNAME);
			derivedDatatypes.add(ID);
			derivedDatatypes.add(IDREF);
			derivedDatatypes.add(IDREFS);
			derivedDatatypes.add(ENTITY);
			derivedDatatypes.add(ENTITIES);
			derivedDatatypes.add(INTEGER);
			derivedDatatypes.add(LONG);
			derivedDatatypes.add(INT);
			derivedDatatypes.add(SHORT);
			derivedDatatypes.add(BYTE);
			derivedDatatypes.add(NON_POSITIVE_INTEGER);
			derivedDatatypes.add(NEGATIVE_INTEGER);
			derivedDatatypes.add(NON_NEGATIVE_INTEGER);
			derivedDatatypes.add(POSITIVE_INTEGER);
			derivedDatatypes.add(UNSIGNED_LONG);
			derivedDatatypes.add(UNSIGNED_INT);
			derivedDatatypes.add(UNSIGNED_SHORT);
			derivedDatatypes.add(UNSIGNED_BYTE);

			allDatatypes.addAll(primitiveDatatypes);
			allDatatypes.addAll(derivedDatatypes);

		}

		public static Set<ARTURIResource> getPrimitiveDatatypes() {
			return primitiveDatatypes;
		}

		public static boolean isXMLPrimitiveDatatype(ARTURIResource dtype) {
			return primitiveDatatypes.contains(dtype);
		}

		public static Set<ARTURIResource> getDerivedDatatypes() {
			return derivedDatatypes;
		}

		public static boolean isXMLDerivedDatatype(ARTURIResource dtype) {
			return derivedDatatypes.contains(dtype);
		}

		public static Set<ARTURIResource> getXMLDatatypes() {
			return allDatatypes;
		}

		public static boolean isXMLDatatype(ARTURIResource dtype) {
			return allDatatypes.contains(dtype);
		}

	}

}
